Rust 的所有權 (Ownership) 概念是Rust核心的一部分,它使Rust能在沒有垃圾收集器的情況下進行記憶體管理,並確保記憶體安全。
Rust 的所有權系統主要基於三個規則:
{ // s 在此處無效,因為它還沒宣告
let s = "hello"; // s 在此開始視為有效
// 使用 s
} // 此作用域結束, s 不再有效
let s1 = String::from("hello");
let s2 = s1;
println!("{}, world!", s1);
這一段程式碼會報錯,String::from 會建立一個String
值並將所有權賦予s1,當 s2 被賦予 s1 時,s1 的所有權將被轉移給 s2。此時,s1 不再引用任何值,因此會被銷毀。
這種情況可以用clone,以python來說就是deep copy
let s1 = String::from("hello");
let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2); // 沒問題!
let s1 = "hello";
let s2 = s1;
println!("{}, world!", s1);
這段程式碼不會報錯,s1 是字面值。字面值是一種在編譯時就被確定的值,"hello" 會在編譯時被轉換為一個 String 值。這個 String 值是不可變的,因此它可以被多次借用。當 s2 被賦予 s1 時,s1 仍然引用該 String 值,因此不會被銷毀。
Rust 通常避免複製數據,而是使用「參考」或「借用」。這可以提高效能並確保記憶體安全性。
建立參考(References)的行為稱為借用(Borrowing)
不可變參考
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("'{}' 的長度是 {}。", s1, len);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
在上面的程式中,calculate_length 函數不擁有 s1 的所有權,只是借用它。因此,當 calculate_length 函數返回後,s1 仍然是 main 函數的,且可以繼續使用。
可變參考
fn main() {
let mut s1 = String::from("hello");
change(&mut s1);
println!("{}", s1);
}
fn change(s: &mut String) {
s.push_str(", world");
}
在上面的code中,s1 是可變的,並被傳遞給 change 函數作為一個可變引用,所以 change 函數可以修改 s1 的內容。
注意,Rust 在特定範圍內只允許一次可變借用,這是為了在編譯時防止資料競爭(data races)。但你可以有多個不可變的借用,因為它們不會修改數據。
資料競爭(data races)引發情況: